package cn.ibizlab.util.common;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.apache.commons.text.StringSubstitutor;
import java.io.*;
import java.util.*;

public class ConfigParser {

    private static final ObjectMapper jsonMapper = new ObjectMapper();
    private static final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());

    public static Map<String, Object> parseConfig(String configStr) {
        try {
            return parseJson(configStr);
        } catch (IOException e) {
            try {
                return parseYaml(configStr);
            } catch (IOException ex) {
                return parseProperties(configStr);
            }
        }
    }

    private static Map<String, Object> parseJson(String jsonStr) throws IOException {
        return jsonMapper.readValue(jsonStr, Map.class);
    }

    private static Map<String, Object> parseYaml(String yamlStr) throws IOException {
        return yamlMapper.readValue(yamlStr, Map.class);
    }

    private static Map<String, Object> parseProperties(String propsStr) {
        Properties props = new Properties();
        try (Reader reader = new StringReader(propsStr)) {
            props.load(reader);
        } catch (IOException e) {
            throw new RuntimeException("Properties parsing failed", e);
        }

        Map<String, Object> resultMap = new HashMap<>();
        props.forEach((k, v) -> {
            String[] keys = k.toString().split("\\.");
            Map<String, Object> current = resultMap;
            for (int i = 0; i < keys.length; i++) {
                String key = keys[i];
                if (i == keys.length - 1) {
                    current.put(key, v.toString());
                } else {
                    current = (Map<String, Object>) current.computeIfAbsent(key, k1 -> new HashMap<>());
                }
            }
        });
        substituteEnvVars(resultMap);
        return resultMap;
    }

    public static Map<String, Object> substituteEnvVars(Map<String, Object> config) {
        StringSubstitutor substitutor = new StringSubstitutor(System.getenv());
        return processMap(config, substitutor);
    }

    private static Map<String, Object> processMap(Map<String, Object> map, StringSubstitutor substitutor) {
        Map<String, Object> result = new HashMap<>();
        map.forEach((key, value) -> {
            if (value instanceof Map) {
                result.put(key, processMap((Map<String, Object>) value, substitutor));
            } else if (value instanceof String) {
                result.put(key, substitutor.replace((String) value));
            } else {
                result.put(key, value);
            }
        });
        return result;
    }

    // 使用示例
    public static void main(String[] args) {
        String jsonConfig = "{\"db\": {\"app\": \"${APP_NAME}\",\"url\": \"jdbc:mysql://${PWD:-localhost}:3306/mydb\"}}";
        String yamlConfig = "app:\n  name: \"${APP_NAME:MyApp}\"";
        String propsConfig = "app=${APP_NAME}\n#server.path=2\nserver.port=${PORT:8080}";

        Map<String, Object> config = parseConfig(propsConfig);
        System.out.println(config); // 输出替换环境变量后的配置
    }
}